/* 做AJAX通信 */
// const { objToParamsStr } = require("../data_utils/string_util");

/* 
requestConf请求配置模板
{
    url: "https://www.httpbin.org/post",
    method: "post",
    data: "username=admin&password=123456",
    headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        Accept: "application/json"
    },
    onSuccess(result) {
        const ret = JSON.parse(result)
        console.log("ret", ret);
    },
    onErr(err) {
        console.error(err)
        document.write(err.msg)
    }
}
*/

/* 
对象转网络请求参数串(params)形式 
例如：{username:admin,password:123456} 转化为 username=admin&password=123456
*/
// console.log(objToParamsStr({ username: "admin", password: "123456" }));
/**
 * 将对象形式的数据转化为【查询参数】格式,eg:
 * { username: "admin", password: "123456" } => ?username=admin&password=123456
 * @param {object} dataObj 数据对象
 * @returns 转化好的【查询参数】字符串
 */
function toSearchParams(dataObj, withQuestionMark = true) {
    let spStr = "";
    for (let key in dataObj) {
        spStr += `${key}=${dataObj[key]}&`;
    }
    // 锯掉最后一个&
    spStr = spStr.slice(0, spStr.length - 1);

    return `${withQuestionMark ? "?" : ""}${spStr}`;
}

const contentType = {
    form: "application/x-www-form-urlencoded",
    json: "application/json",
};

function ajax(conf) {
    const xhr = new XMLHttpRequest();
    // let { method, url, dataType, data, onSuccess, onFail } = conf;

    // 默认配置
    const defConf = {
        method: "GET",
        accept: "json",
        onSuccess: (data) => console.log("data=", data),
        onFail: (err) => console.error("err=", err),
    };

    // 整合默认配置与用户配置 然后重新解构
    let { method, url, accept, dataType, data, onSuccess, onFail } = {
        ...defConf,
        ...conf,
    };

    /* 提前处理一些异常情况 */
    if (!url) {
        // 对调用者抛出炸弹（携带一些友好的"教育信息"）
        // 程序至此结束(不会继续往下执行了)
        throw new Error("请传入URL我亲爱的傻鸟");
    }

    // 发送调用者传入的数据
    if (method === "GET" && data) {
        // { username: "admin", password: "123456" } => ?username=admin&password=123456
        url += toSearchParams(data);
    }

    // 调用者需要告诉我请求的方法+URL
    xhr.open(method, url);

    if (method !== "GET" && data) {
        xhr.setRequestHeader("Content-Type", dataType);

        // ?username=admin&password=123456
        if (dataType === contentType.form) {
            xhr.send(toSearchParams(data, false));
        } else {
            xhr.send(JSON.stringify(data));
        }
    } else {
        xhr.send(null);
    }

    xhr.onload = function (e) {
        const ret = xhr.responseText;
        onSuccess(accept === "json" ? JSON.parse(ret) : ret);
    };

    xhr.onerror = function (err) {
        onFail(err);
    };
}

/* 立刻返还调用者一个用于执行AJAX的Promise对象 但该对象将来会走向履约OR毁约 不得而知 */
function ajaxPromise(conf) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        // let { method, url, dataType, data, onSuccess, onFail } = conf;

        // 默认配置
        const defConf = {
            method: "GET",
            accept: "json",
            // onSuccess: (data) => console.log("data=", data),
            // onFail: (err) => console.error("err=", err),
        };

        // 整合默认配置与用户配置 然后重新解构
        let { method, url, accept, dataType, data, onSuccess, onFail } = {
            ...defConf,
            ...conf,
        };

        /* 提前处理一些异常情况 */
        if (!url) {
            // 对调用者抛出炸弹（携带一些友好的"教育信息"）
            // 程序至此结束(不会继续往下执行了)
            throw new Error("请传入URL我亲爱的傻鸟");
        }

        // 发送调用者传入的数据
        if (method === "GET" && data) {
            // { username: "admin", password: "123456" } => ?username=admin&password=123456
            url += toSearchParams(data);
        }

        // 调用者需要告诉我请求的方法+URL
        xhr.open(method, url);

        if (method !== "GET" && data) {
            xhr.setRequestHeader("Content-Type", dataType);

            // ?username=admin&password=123456
            if (dataType === contentType.form) {
                xhr.send(toSearchParams(data, false));
            } else {
                xhr.send(JSON.stringify(data));
            }
        } else {
            xhr.send(null);
        }

        xhr.onload = function (e) {
            const ret = xhr.responseText;
            // onSuccess(accept === "json" ? JSON.parse(ret) : ret);
            resolve(accept === "json" ? JSON.parse(ret) : ret);
        };

        xhr.onerror = function (err) {
            // onFail(err);
            reject(err);
        };
    });
}
